using System;
using System.Collections.Generic;
using System.Windows.Browser;

namespace HtmlUtilities
{
    public interface IHtmlObject : IScriptObject
    {
        bool AttachEvent(string eventName, EventHandler handler);
        bool AttachEvent(string eventName, Action<object, IHtmlEventArgs> handler);
        void DetachEvent(string eventName, EventHandler handler);
        void DetachEvent(string eventName, Action<object, IHtmlEventArgs> handler);
    }

    internal class HtmlObjectWrapper : ScriptObjectWrapper, IHtmlObject
    {
        private readonly HtmlObject _htmlObject;
        public HtmlObjectWrapper(HtmlObject htmlObject) : base(htmlObject)
        {
            _htmlObject = htmlObject;
        }
        
        public bool AttachEvent(string eventName, EventHandler handler)
        {
            return _htmlObject.AttachEvent(eventName, handler);
        }

        private class ActionCommand
        {
            public event Action<object, IHtmlEventArgs> Action;

            public bool HasActions { get { return Action != null; } }

            public void Execute(object sender, IHtmlEventArgs args)
            {
                if(HasActions)
                    Action(sender, args);
            }
        }

        private readonly Dictionary<string, ActionCommand> _actions = new Dictionary<string, ActionCommand>();
        private bool AddAction(string eventName, Action<object, IHtmlEventArgs> action)
        {
            var result = false;

            if (!_actions.ContainsKey(eventName))
            {
                _actions.Add(eventName, new ActionCommand());
                result = true;
            }

            _actions[eventName].Action += action;

            return result;
        }

        private bool RemoveAction(string eventName, Action<object, IHtmlEventArgs> action)
        {
            var result = false;

            if(!_actions.ContainsKey(eventName))
                return false;

            _actions[eventName].Action -= action;

            if (!_actions[eventName].HasActions)
            {
                _actions.Remove(eventName);
                result = true;
            }

            return result;
        }

        private void ExectionAction(object sender, HtmlEventArgs args)
        {
            if(!_actions.ContainsKey(args.EventType))
                return;

            _actions[args.EventType].Execute(sender, new HtmlEventArgsWrapper(args));
        }

        public bool AttachEvent(string eventName, Action<object, IHtmlEventArgs> handler)
        {
            if(AddAction(eventName, handler))
                return _htmlObject.AttachEvent(eventName, ExectionAction);

            return true;
        }

        public void DetachEvent(string eventName, EventHandler handler)
        {
            _htmlObject.DetachEvent(eventName, handler);
        }

        public void DetachEvent(string eventName, Action<object, IHtmlEventArgs> handler)
        {
            if(RemoveAction(eventName, handler))
                _htmlObject.DetachEvent(eventName, ExectionAction);
        }
    }

    
}